package com.boss.ccs.cpm;

import com.boss.Messages;
import com.boss.core.BossConstants;
import com.boss.core.common.Target;
import com.boss.core.form.BossForm;
import com.boss.core.form.BossFormHelper;
import com.boss.core.manage.BossProperty;
import com.boss.core.manage.PropertySection;
import com.boss.core.util.BossGlobalUtil;
import com.boss.core.util.BossUtil;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.StaplerRequest;

import javax.servlet.ServletException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Boss CPM Form
 * @author Momin Noor Khan
 */
public class BossCPMForm extends BossForm {
    private boolean isTargetSection;
    private String targetProfile;
    private boolean isExistingBuildBlock;
    private String existingBuildNumber;
    private boolean installer = false;
    private boolean messaging = false;
    private boolean ccsMobileClient = false;
    private String customer = "";
    private String language = "";
    private boolean onlineHelpBlock = false;
    private String helpArtifacts = "";

    //Getter and Setters
    public boolean isTargetSection() {
        return isTargetSection;
    }

    public void setTargetSection(boolean targetSection) {
        isTargetSection = targetSection;
    }

    public String getTargetProfile() {
        return targetProfile;
    }

    public void setTargetProfile(String targetProfile) {
        this.targetProfile = targetProfile;
    }

    public boolean isExistingBuildBlock() {
        return isExistingBuildBlock;
    }

    public void setExistingBuildBlock(boolean existingBuildBlock) {
        isExistingBuildBlock = existingBuildBlock;
    }

    public String getExistingBuildNumber() {
        return existingBuildNumber;
    }

    public void setExistingBuildNumber(String existingBuildNumber) {
        this.existingBuildNumber = existingBuildNumber;
    }

    public boolean isInstaller() {
        return installer;
    }

    public void setInstaller(boolean installer) {
        this.installer = installer;
    }

    public boolean isMessaging() {
        return messaging;
    }

    public void setMessaging(boolean messaging) {
        this.messaging = messaging;
    }

    public boolean isCcsMobileClient() {
        return ccsMobileClient;
    }

    public void setCcsMobileClient(boolean ccsMobileClient) {
        this.ccsMobileClient = ccsMobileClient;
    }

    public String getCustomer() {
        return customer;
    }

    public void setCustomer(String customer) {
        this.customer = customer;
    }

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }

    public boolean isOnlineHelpBlock() {
        return onlineHelpBlock;
    }

    public void setOnlineHelpBlock(boolean onlineHelpBlock) {
        this.onlineHelpBlock = onlineHelpBlock;
    }

    public String getHelpArtifacts() {
        return helpArtifacts;
    }

    public void setHelpArtifacts(String helpArtifacts) {
        this.helpArtifacts = helpArtifacts;
    }

    public BossCPMForm(StaplerRequest req, JSONObject jsonForm, String project) {
        super(req, jsonForm, project);
        isTargetSection = BossUtil.contains(getJsonTaskSection(), BossConstants.KEY_TARGET);
        targetProfile = BossFormHelper.getTargetProfile(isTargetSection, req);
        isExistingBuildBlock = BossUtil.contains(getJsonTaskSection(), BossConstants.KEY_EXISTING_BUILD_BLOCK);
        existingBuildNumber = BossUtil.getStringValueFromJson(getJsonTaskSection(), BossConstants.KEY_EXISTING_BUILD_BLOCK,
                BossConstants.KEY_EXISTING_BUILD_NUMBER);
        installer = BossUtil.getBooleanValueFromJson(getJsonTaskSection(), BossConstants.KEY_INSTALLER);
        messaging = BossUtil.getBooleanValueFromJson(getJsonTaskSection(), BossConstants.KEY_MESSAGING);
        ccsMobileClient = BossUtil.getBooleanValueFromJson(getJsonTaskSection(), BossConstants.KEY_CCS_MOBILE_CLIENT);
        onlineHelpBlock = BossUtil.contains(getJsonTaskSection(), BossConstants.KEY_ONLINE_HELP_BLOCK);
        customer = getSelectedCustomer(getJsonTaskSection(), onlineHelpBlock, getTask());
        language = getSelectedLanguage(getJsonTaskSection(), onlineHelpBlock, getTask());
        helpArtifacts = getSelectedHelpArtifacts(getTask(), getJsonTaskSection());
    }

    @Override
    public void prepareUrlParamMap() {
        super.prepareUrlParamMap();
        Map<String, String> map = getUrlMap();
        map.put(BossConstants.URL_PARAM_TARGET_PROFILE, targetProfile);
        if(isExistingBuildBlock) {
            map.put(BossConstants.URL_PARAM_EXISTING_BUILD_NUMBER, existingBuildNumber);
        }
        map.put(BossConstants.URL_PARAM_INSTALLER, String.valueOf(installer));
        map.put(BossConstants.URL_PARAM_MESSAGING, String.valueOf(messaging));
        map.put(BossConstants.URL_PARAM_CCS_MOBILE_CLIENT, String.valueOf(ccsMobileClient));
        map.put(BossConstants.URL_PARAM_CUSTOMER, customer);
        map.put(BossConstants.URL_PARAM_LANGUAGE, language);
        map.put(BossConstants.URL_PARAM_HELP_ARTIFACTS, helpArtifacts);
        setUrlMap(map);
    }

    public String getSelectedHelpArtifacts(String task, JSONObject jsonTaskSection) {
        String helpArtifacts = "";
        if (task.equals(BossConstants.TASK_DEPLOY_HELP)) {
            List<BossProperty> artifacts = getAllHelpArtifacts();
            for (BossProperty artifact : artifacts) {
                if (jsonTaskSection != null && jsonTaskSection.has(artifact.getName())) {
                    if (jsonTaskSection.getBoolean(artifact.getName())) {
                        helpArtifacts = helpArtifacts + StringUtils.strip(artifact.getName()) + ",";
                    }
                }
            }
            helpArtifacts = StringUtils.removeEnd(helpArtifacts, ",");
        }
        return helpArtifacts;
    }

    public List<BossProperty> getAllHelpArtifacts() {
        PropertySection propertySection = BossGlobalUtil.getPropertySection(BossConstants.ONLINE_HELP_ARTIFACTS_KEY);
        List<BossProperty> properties = propertySection.getProperties();
        return properties;
    }

    public String getSelectedCustomer(JSONObject jsonObject, boolean isOnlineHelpChecked, String task) {
        String customer = "";
        if (!StringUtils.isBlank(task)) {
            if (isOnlineHelpChecked) {
                customer = jsonObject.getJSONObject(BossConstants.KEY_ONLINE_HELP_BLOCK).getString(BossConstants.KEY_CUSTOMER);
            } else if (jsonObject.has(BossConstants.KEY_CUSTOMER)) {
                customer = jsonObject.getString(BossConstants.KEY_CUSTOMER);
            } else if (!StringUtils.isBlank(task) && task.equals(BossConstants.TASK_DEPLOY)) {
                customer = BossGlobalUtil.getPropertyValue(BossConstants.PROJECT_CPM, BossConstants.ONLINE_HELP_DEFAULT_CUSTOMER_KEY);
            }
        }
        return customer;
    }

    public String getSelectedLanguage(JSONObject jsonObject, boolean isOnlineHelpChecked, String task) {
        String language = "";
        if (!StringUtils.isBlank(task)) {
            if (isOnlineHelpChecked) {
                language = jsonObject.getJSONObject(BossConstants.KEY_ONLINE_HELP_BLOCK).getString(BossConstants.KEY_LANGUAGE);
            } else if (jsonObject.has(BossConstants.KEY_LANGUAGE)) {
                language = jsonObject.getString(BossConstants.KEY_LANGUAGE);
            } else if (!StringUtils.isBlank(task) && task.equals(BossConstants.TASK_DEPLOY)) {
                language = BossGlobalUtil.getPropertyValue(BossConstants.PROJECT_CPM, BossConstants.ONLINE_HELP_DEFAULT_LANGUAGE_KEY);
            }
        }
        return language;
    }

    @Override
    public boolean isValid() {
        boolean valid = true;
        if (!checkMandatoryFields() |
                !checkExistingBuildNumber() |
                !checkTargetProfile() |
                !checkInstaller() |
                !checkOnlineHelp() |
                !checkHelp() |
                !checkMessaging()
                ) {
            valid = false;
        } else if (!BossFormHelper.checkAvailableJob(getRequest(), getAvailableJob())) {
            valid = false;
        }
        return valid;
    }

    public boolean checkMandatoryFields() {
        boolean valid = true;
        StaplerRequest req = getRequest();
        String project = getProject();
        String release = getRelease();
        String task = getTask();
        if (!BossFormHelper.checkProject(req, project) |
                !BossFormHelper.checkRelease(req, release) |
                !BossFormHelper.checkTask(req, task)) {
            valid = false;
        }
        return valid;
    }

    /**
     * Performs post-submit validation for target profiles
     * Validation - At least one target container must be selected if the task type is 'deploy*'
     * Target container is a combination of environment-server-port instance
     */
    public boolean checkTargetProfile() {
        boolean valid = true;
        StaplerRequest req = getRequest();
        String task = getTask();
        String targetProfile = getTargetProfile();
        if (!StringUtils.isBlank(task)
                &&
                (task.equals(BossConstants.TASK_DEPLOY) ||
                        task.equals(BossConstants.TASK_DEPLOY_EXISTING_MESSAGING_ONLY) ||
                        task.equals(BossConstants.TASK_DEPLOY_HELP))) {
            if (StringUtils.isBlank(targetProfile)) {
                BossFormHelper.setValidationErrorMsg(req, Messages.Boss_MandatoryTarget(task));
                valid = false;
            }
        }
        return valid;
    }

    /**
     * Performs post-submit validation for existing build number
     * Validation - mandatory if the task type is deploy and CheckBox is checked (TO-DO add comment for other relevant scenarios)
     */
    public boolean checkExistingBuildNumber() {
        boolean valid = true;
        StaplerRequest req = getRequest();
        boolean existingBuildBlock = isExistingBuildBlock();
        String existingBuildNumber = getExistingBuildNumber();
        String task = getTask();
        if (!StringUtils.isBlank(task)) {
            if (existingBuildBlock) {
                if (BossUtil.isBlankOrDummy(existingBuildNumber)) {
                    BossFormHelper.setValidationErrorMsg(req, Messages.BossCPM_MandatoryExistingBuildNumberIfChecked(task));
                    valid = false;
                }
            } else if (isMandatoryExistingBuildBlockOrNumberMissing(task, existingBuildBlock, existingBuildNumber)) {
                BossFormHelper.setValidationErrorMsg(req, Messages.Boss_MandatoryExistingBuildNumber(task));
                valid = false;
            }
        }
        return valid;
    }

    public boolean isMandatoryExistingBuildBlockOrNumberMissing(String task, boolean existingBuildBlock, String existingBuildNumber) {
        if ((task.equals(BossConstants.TASK_INSTALLER)
                || task.equals(BossConstants.TASK_DEPLOY_EXISTING_MESSAGING_ONLY))
                && (!existingBuildBlock || BossUtil.isBlankOrDummy(existingBuildNumber))) {
            return true;
        }
        return false;
    }

    /**
     * Performs post-submit validation for installer checkbox
     */
    public boolean checkInstaller() {
        boolean valid = true;
        StaplerRequest req = getRequest();
        boolean installer = isInstaller();
        String task = getTask();
        //throw error if 'installer' check-box is checked and task type is other than 'deploy'
        if ((!StringUtils.isBlank(task)
                &&
                !(task.equals(BossConstants.TASK_DEPLOY) ||
                        !task.equals(BossConstants.TASK_RELEASE) ||
                        !task.equals(BossConstants.TASK_INSTALLER)))
                &&
                installer) {
            BossFormHelper.setValidationErrorMsg(req, Messages.BossCPM_ValidTaskRequiredForInstaller(BossConstants.TASK_DEPLOY + "/" + BossConstants.TASK_RELEASE + "/" + BossConstants.TASK_INSTALLER));
            valid = false;
        }
        return valid;
    }

    /**
     * Performs post-submit validation for online help checkbox
     */
    public boolean checkOnlineHelp() {
        boolean valid = true;
        StaplerRequest req = getRequest();
        //boolean onlineBlock = isOnlineHelpBlock();
        //String customer = getCustomer();
        //String language = getLanguage();          why were they used as param earlier??
        String task = getTask();
        //throw error if 'online help' check-box is checked and the task type is other than 'deploy'
        if ((!StringUtils.isBlank(task) && !task.equals(BossConstants.TASK_DEPLOY) && onlineHelpBlock)) {
            BossFormHelper.setValidationErrorMsg(req, Messages.BossCPM_ValidTaskRequiredForOnlineHelp(BossConstants.TASK_DEPLOY));
            valid = false;
        }
        return valid;
    }

    public boolean checkHelp() {
        boolean valid = true;
        StaplerRequest req = getRequest();
        String task = getTask();
        String release = getRelease();
        String language = getLanguage();
        String helpArtifacts = getHelpArtifacts();
        if (!StringUtils.isBlank(task) && task.equals(BossConstants.TASK_DEPLOY_HELP)) {
            if (StringUtils.isBlank(language) || language.equals(BossConstants.DUMMY_VALUE)) {
                BossFormHelper.setValidationErrorMsg(req, Messages.Boss_MandatoryLanguage(task));
                valid = false;
            }

            if (StringUtils.isBlank(helpArtifacts)) {
                BossFormHelper.setValidationErrorMsg(req, Messages.Boss_MandatoryHelpArtifact(task));
                valid = false;
            }
        }
        return valid;
    }

    public boolean checkMessaging() {
        boolean valid = true;
        StaplerRequest req = getRequest();
        boolean messaging = isMessaging();
        String task = getTask();

        if (!StringUtils.isBlank(task) && !task.equals(BossConstants.TASK_DEPLOY) && messaging) {
            BossFormHelper.setValidationErrorMsg(req, Messages.BossCPM_ValidTaskRequiredForMessaging(BossConstants.TASK_DEPLOY));
            valid = false;
        }
        return valid;
    }
}
